#ifndef VECTOR_H_
#define VECTOR_H_

#include <vector>
#include <sstream>
#include <cmath>

namespace om
{

template<int SIZE>
class vector
{
public:
	enum {size=SIZE};

	vector() : v_(size, 0)
	{
	}

	double operator[](int i) const { return v_[i]; }

	double& operator[](int i) { return v_[i]; }

	bool operator==(const vector& v) const
	{
		for(int i=0;i<size;i++)
		{
			if((*this)[i]!=v[i]) {return false;};
		}
		return true;
	}

	bool operator!=(const vector& v) const
	{
		return (!((*this)==v));
	}

	vector operator!() const
	{
		vector r;
		for(int i=0;i<size;i++) { r[i]=0.0-(*this)[i]; }
		return r;
	}

	vector operator*(double k) const
	{
		vector r;
		for(int i=0;i<size;i++) { r[i]=(*this)[i]*k; }
		return r;
	}

	vector operator/(double k) const
	{
		return ((*this)*(1.0/k));
	}

	vector operator+(const vector& v) const
	{
		vector r;
		for(int i=0;i<size;i++) { r[i]=(*this)[i]+v[i]; }
		return r;
	}

	vector operator-(const vector& v) const
	{
		return ((*this)+(!v));
	}

	double operator*(const vector& v) const
	{
		double sum=0.0;
		for(int i=0;i<size;i++) { sum+=(*this)[i]*v[i]; }
		return sum;
	}

	double norm() const
	{
		return sqrt((*this)*(*this));
	}

	vector unit() const
	{
		return (*this)/norm();
	}

	std::string to_string() const
	{
		std::ostringstream output;
		for(int i=0;i<size;i++) { output << (*this)[i] << (i+1<size ? " " : ""); }
		return output.str();
	}

	static vector from_stream(std::istream& input)
	{
		vector v;
		for(int i=0;i<size;i++) { input >> v[i]; }
		return v;
	}

private:
	std::vector<double> v_;
};

}

#endif /* VECTOR_H_ */
